"use strict"

const Service = require('egg').Service
const fs = require("fs");
const path = require("path");

class UploadService extends Service {
    /**
     * 
     * @param {查询图片} param 
     * page,rows,mkdir(否)
     */
    async imgs_list(param) {
        const { app, ctx } = this
        const mkdir = param.mkdir
        const page = param.page
        const rows = param.rows
        let where = {
            admin_id: 1
        }
        if(mkdir != -1 || !mkdir){
            where.mkdir = mkdir
        }
        try{
            let result = await app.model.Imgs.findAndCountAll({
                where,
                limit: Number(rows),
                offset: (page - 1)*rows
            })
            
            return ctx.app.returnHint(result, '查询成功').definedSucceed
        }catch(err) {
            console.log(err)
            return ctx.app.returnHint(err, '查询失败').definedError
        }
    }

    /**
     * @param {删除图片} param 
     * imgs_id
     */
    async del_imgs(param) {
        const { app, ctx } = this
        // 基础目录
        const uplaodBasePath = 'app/';
        const files = param.imgs_id
        let target
        let result
        // 开始事务
        const transaction = await app.model.transaction();
        try{
            for(let id of files) {
                let where = {
                    admin_id: 1,
                    id: id
                }
                result = await app.model.Imgs.findOne({
                    where,
                    transaction
                })
                await result.destroy({
                    where,
                    transaction
                })
                target = path.join(uplaodBasePath, result.path)
                if (fs.existsSync(target)){
                    fs.unlinkSync(target);
                }
            }
            // 提交事务
            await transaction.commit();
            return ctx.app.returnHint(result, '删除成功').definedSucceed
        }catch(err){
            console.log(err)
            await transaction.rollback();// 捕获异常后回滚事务！！
            // 写入流
            const writeStream = fs.createWriteStream(target);
            // 读取流
            const readStream = fs.createReadStream(target);// 创建可读流
            readStream.pipe(writeStream);

            return ctx.app.returnHint(err, '删除失败').definedError
        }
    }

    /**
     * @param {查询目录} param 
     * 
     */
    async list_mkdir() {
        const { ctx } = this
        // 基础目录
        const uplaodBasePath = 'app/public/upload/';
        //存储所有的文件夹
        let allMkdir = [];
        try{
            let files = fs.readdirSync(uplaodBasePath)
             files.forEach((flie) => {
                let absolutePath = path.join(uplaodBasePath, flie);
                let stats = fs.lstatSync(absolutePath);
                if (stats.isDirectory()) {
                    allMkdir.push(flie)
                }
            })
            return ctx.app.returnHint(allMkdir, '查询成功').definedSucceed
        }catch(err) {
            console.log(err)
            return ctx.app.returnHint(err, '查询失败').definedError
        }
    }

    /**
     * 
     * @param {新增目录} param 
     * mkdir
     * 
     */
    async add_mkdir(param) {
        const { config, ctx } = this
        // 基础目录
        const uplaodBasePath = 'app/public/upload/';
        // 判断目录是否存在，不存在则直接创建文件夹
        try{
            if (!fs.existsSync(uplaodBasePath + param.mkdir)){
                fs.mkdirSync(path.join(config.baseDir, uplaodBasePath, param.mkdir))
                return ctx.app.returnHint(param.mkdir, '添加成功').definedSucceed
            }else{
                return ctx.app.returnHint(null, '目录已存在').definedSucceed
            }
        }catch(err) {
            console.log(err)
            if (fs.existsSync(uplaodBasePath + param.mkdir)){
                fs.rmdirSync(path.join(config.baseDir, uplaodBasePath, param.mkdir))
            }
            
            return ctx.app.returnHint(err, '添加失败').definedError
        }
    }

    /**
     * 
     * @param {删除目录} param 
     * mkdir
     * 
     */
    async del_mkdir(param){
        const { config, app, ctx } = this
        // 开始事务
        const transaction = await app.model.transaction();
        // 基础目录
        const uplaodBasePath = 'app/public/upload/';
        let target
        try{
            // 判断目录是否存在
            if (fs.existsSync(uplaodBasePath + param.mkdir)){
                let files = fs.readdirSync(uplaodBasePath + param.mkdir)
                for(let file of files) {
                    target = path.join(config.baseDir, uplaodBasePath, param.mkdir, file)
                    let where = {
                        admin_id: 1,
                        path: path.join('public/upload/', param.mkdir, file)
                    }
                    await app.model.Imgs.destroy({
                        where,
                        transaction
                    })
                    s.unlinkSync(target); 
                }
                fs.rmdirSync(path.join(config.baseDir, uplaodBasePath, param.mkdir))
                // 提交事务
                await transaction.commit();
                return ctx.app.returnHint(true, '删除成功').definedSucceed
            }else{
                return ctx.app.returnHint(null, '目录不存在').definedSucceed
            }
        }catch(err) {
            console.log(err)
            await transaction.rollback();// 捕获异常后回滚事务！！
            // 写入流
            const writeStream = fs.createWriteStream(target);
            // 读取流
            const readStream = fs.createReadStream(target);// 创建可读流
            readStream.pipe(writeStream);
            
            return ctx.app.returnHint(err, '删除失败').definedError
        }
    }

    /**
     * 
     * @param {移动目录} param 
     * mkdir, imgs_id
     * 
     */
    async move_mkdir(param){
        const { config, app, ctx } = this
        // 开始事务
        const transaction = await app.model.transaction();
        // 基础目录
        const uplaodBasePath = 'app/';
        const uplaodPath = 'public/upload/'
        let targetMkdir = ''  // 目标目录
        const moveMkdir = param.mkdir      // 移动目录
        const files = param.imgs_id // 移动文件
        const array = []
        let target, moveTarget
        try{
            for(let id of files){
                let result = await app.model.Imgs.findOne({
                    where: {
                        id
                    }
                })         
                if(result.mkdir !== moveMkdir){
                    let filename = result.filename;
                    targetMkdir = result.mkdir == '0'? '' : result.mkdir
                    // 移动的文件路径             
                    let filePath = uplaodPath + moveMkdir + '/' + filename
                    // 修改数据库目录
                    await result.update({ mkdir: moveMkdir, path: filePath }, {
                        where: {
                            id: result.id
                        },
                        transaction
                    })
                    array.push(filePath)
                    // 原有的文件
                    target = path.join(config.baseDir, uplaodBasePath, uplaodPath, targetMkdir, filename);	
                    // 移动路径生成写入路径
                    moveTarget = path.join(config.baseDir, uplaodBasePath, uplaodPath, moveMkdir, filename);
                    // 移动
                    fs.renameSync(target, moveTarget)
                }
            }
            // 提交事务
            await transaction.commit();
            return ctx.app.returnHint(array, '移动目录成功').definedSucceed
        }catch(err) {
            console.log(err)
            // 文件还原
            fs.renameSync(moveTarget, target)
            array = []
            await transaction.rollback();// 捕获异常后回滚事务！！
            
            return ctx.app.returnHint(err, '移动目录失败').definedError
        }
    }
}

module.exports = UploadService